<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>元素尺寸</title>
  <style>
    #app{
      width: 300px;
      height:300px;
      padding:250px;
      border:1px solid red;
    }
    .son{
      height: 150px;
      width: 150px;
      border:1px solid rebeccapurple;
    }
    .father{
      position: relative;
    }
  </style>
</head>
<body>
  <div id="app">
     <div class="father">
      <div class="son">偏移尺寸</div>
     </div>
  </div>
</body>
<script>
  /** 1. 偏移尺寸
   *    a.第一组属性涉及偏移尺寸（offset dimensions），包含元素在屏幕上占用的所有视觉空间。元素在页面上的视觉空间由其高度和宽度决定，包括所有内边距、滚动条
          和边框（但不包含外边距）。以下 4 个属性用于取得元素的偏移尺寸。
          + offsetHeight，元素在垂直方向上占用的像素尺寸，包括它的高度、水平滚动条高度（如果可见）和上、下边框的高度。
          + offsetWidth，元素在水平方向上占用的像素尺寸，包括它的宽度、垂直滚动条宽度（如果可见）和左、右边框的宽度。
          + offsetLeft，元素左边框外侧距离包含元素左边框内侧的像素数。
          + offsetTop，元素上边框外侧距离包含元素上边框内侧的像素数。
        b.其中，offsetLeft 和 offsetTop 是相对于包含元素的，包含元素保存在 offsetParent 属性中。offsetParent 不一定是 parentNode。比如，<td>元素
          的 offsetParent 是作为其祖先的<table>元素，因为<table>是节点层级中第一个提供尺寸的元素。
        c.要确定一个元素在页面中（相对于<body>）的偏移量，可以把它的 offsetLeft 和 offsetTop 属性分别与 offsetParent的相同属性相加，一直加到根元素。
        d.一般来说，包含在<div>元素中所有元素都以<body>为其 offsetParent，因此 getElementleft()和 getElementTop()返回的值与 offsetLeft 和 
          offsetTop 返回的值相同。(实践发现，当父元素采用了 position:relatvie时候，子元素的 offsetParent 为父元素，而不是为 body元素)
        e.所有这些偏移尺寸属性都是只读的，每次访问都会重新计算。因此，应该尽量减少查询它们的次数。比如把查询的值保存在局量中，就可以避免影响性能。
    **/
    function checkOffset(){
      //.app 与 body 偏移量
      let app = document.querySelector('#app');
      console.log(app.offsetLeft);//8
      console.log(app.offsetTop);//8
      console.log(app.offsetParent);//body
      //.father 与 body 偏移量
      let father = document.querySelector('.father');
      console.log(father.offsetLeft);//259==> 8 + 1 + 250 
      console.log(father.offsetTop);//259==> 8 + 1 + 250 
      console.log(father.offsetParent);//body
      //.son 与 .father 偏移量
      let son = document.querySelector('.son');
      console.log(son.offsetLeft);//0
      console.log(son.offsetTop);//0
      console.log(son.offsetParent);//div.father
    }
    // checkOffset();
    // 确定一个元素在页面中的偏移量，可
    function getElementLeftAndTop(ele){
      let actualLeft = ele.offsetLeft;
      let actualTop  = ele.offsetTop;
      let currentParent = ele.offsetParent;
      while(currentParent !== null){
        actualLeft += currentParent.offsetLeft;
        actualTop  += currentParent.offsetTop;
        currentParent = currentParent.offsetParent;
      }
      return {offsetLeft:actualLeft,offsetTop:actualTop}
    };
    //这个函数使用 offsetParent 在 DOM 树中逐级上溯，将每一级的偏移属性相加，最终得到元素的实际偏移量。对于使用 CSS 布局的简单页面，这两个函数是很精确的。而
    //对于使用表格和内嵌窗格的页面布局，它们返回的值会因浏览器不同而有所差异，因为浏览器实现这些元素的方式不同。
    // let app = document.querySelector('#app');
    // let father = document.querySelector('.father');
    // let son = document.querySelector('.son');
    // console.log(getElementLeftAndTop(app));//{offsetLeft: 8, offsetTop: 8}
    // console.log(getElementLeftAndTop(father));//{offsetLeft: 259, offsetTop: 259}
    // console.log(getElementLeftAndTop(son));//{offsetLeft: 259, offsetTop: 259}


  /** 2. 客户端尺寸
   *     a.元素的客户端尺寸（client dimensions）包含元素内容及其内边距所占用的空间。客户端尺寸只有两个相关属性：clientWidth 和 clientHeight。其中，
   *       clientWidth 是内容区宽度加左、右内边距宽度，clientHeight 是内容区高度加上、下内边距高度。
   *     b.客户端尺寸实际上就是元素内部的空间，因此不包含滚动条占用的空间。这两个属性最常用于确定浏览器视口尺寸，即检测 document.documentElement 的 
   *       clientWidth 和 clientHeight。这两个属性表示视口（<html>或<body>元素）的尺寸.
   *     c.与偏移尺寸一样，客户端尺寸也是只读的，而且每次访问都会重新计算。
   * **/
</script>
</html>
